package com.pzhu.dormitory.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pzhu.dormitory.dao.MenuDao;
import com.pzhu.dormitory.entity.MenuEntity;
import com.pzhu.dormitory.entity.MenuRoleRelationshipEntity;
import com.pzhu.dormitory.entity.RoleEntity;
import com.pzhu.dormitory.service.MenuRoleRelationshipService;
import com.pzhu.dormitory.service.MenuService;
import com.pzhu.dormitory.service.RoleService;
import com.pzhu.dormitory.service.UserService;
import com.pzhu.dormitory.utils.PageUtils;
import com.pzhu.dormitory.utils.Query;
import com.pzhu.dormitory.vo.MenuNode;
import com.pzhu.dormitory.vo.MenuRoleVo;
import com.pzhu.dormitory.vo.RoleVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuDao, MenuEntity> implements MenuService {

    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuRoleRelationshipService menuRoleRelationshipService;
    @Autowired
    private UserService userService;

    @Override
    public PageUtils<MenuEntity> queryPage(Map<String, Object> params) {
        QueryWrapper<MenuEntity> queryWrapper = new QueryWrapper<>();
        String name = (String) params.get("name");
        if (StringUtils.isNotBlank(name)) {
            queryWrapper.lambda().like(MenuEntity::getName, "%" + name + "%");
        }
        IPage<MenuEntity> page = this.page(
                new Query<MenuEntity>().getPage(params),
                queryWrapper
        );
        return new PageUtils<>(page);
    }

    @Override
    public MenuNode loadMenu() {
        List<MenuEntity> list = this.list();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<Long> longList = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).map(Long::parseLong).collect(Collectors.toList());
        LambdaQueryChainWrapper<MenuRoleRelationshipEntity> wrapper = menuRoleRelationshipService.lambdaQuery().in(MenuRoleRelationshipEntity::getRoleId, longList);
        List<Long> collect = wrapper.list().stream().map(MenuRoleRelationshipEntity::getMenuId).collect(Collectors.toList());
        list = list.stream().filter(menuEntity -> collect.contains(menuEntity.getId())).collect(Collectors.toList());
        Long index = -1L;
        MenuNode menuNode = MenuNode.builder().build();
        load(list, index, menuNode);
        return menuNode;
    }

    @Override
    public MenuRoleVo loadRoles(String menuId) {
        MenuRoleVo menuRoleVo = new MenuRoleVo();
        List<RoleEntity> list = roleService.list();
        List<RoleVo> roleVos = list.stream().map(roleEntity -> {
            RoleVo roleVo = new RoleVo();
            BeanUtils.copyProperties(roleEntity, roleVo);
            return roleVo;
        }).collect(Collectors.toList());
        menuRoleVo.setAllRole(roleVos);
        List<Long> collect = menuRoleRelationshipService.list(new LambdaQueryWrapper<MenuRoleRelationshipEntity>()
                .eq(MenuRoleRelationshipEntity::getMenuId, menuId)).stream().map(MenuRoleRelationshipEntity::getRoleId).collect(Collectors.toList());
        menuRoleVo.setOwnRoles(collect);
        return menuRoleVo;
    }

    /**
     * 递归加载菜单
     *
     * @param list
     * @param index
     * @param menuNode
     */
    private void load(List<MenuEntity> list, Long index, MenuNode menuNode) {
        // index 的 节点
        List<MenuEntity> indexMenuEntityList = new ArrayList<>();
        // 剩下 的 节点
        List<MenuEntity> surplusMenuEntityList = new ArrayList<>();
        list.forEach(menuEntity -> {
            if (menuEntity.getPid().equals(index)) {
                indexMenuEntityList.add(menuEntity);
            } else {
                surplusMenuEntityList.add(menuEntity);
            }
        });
        List<MenuNode> collect = indexMenuEntityList.stream().map(menuEntity -> {
            MenuNode node = MenuNode.builder().id(menuEntity.getId()).title(menuEntity.getName()).url(menuEntity.getUrl()).build();
            load(surplusMenuEntityList, node.getId(), node);
            return node;
        }).collect(Collectors.toList());
        menuNode.setChildren(collect);
    }

}
